home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Sprite 1984 - 1993
/
Sprite 1984 - 1993.iso
/
src
/
kernel
/
sig
/
sigStubs.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-12-18
|
13KB
|
492 lines
/*
* sigStubs.c --
*
* Stubs for Unix compatible system calls.
*
* Copyright 1990 Regents of the University of California
* Permission to use, copy, modify, and distribute this
* software and its documentation for any purpose and without
* fee is hereby granted, provided that the above copyright
* notice appear in all copies. The University of California
* makes no representations about the suitability of this
* software for any purpose. It is provided "as is" without
* express or implied warranty.
*/
#ifndef lint
static char rcsid[] = "$Header: /cdrom/src/kernel/Cvsroot/kernel/sig/sigStubs.c,v 1.8 92/05/10 14:17:08 shirriff Exp $";
#endif /* not lint */
#define MACH_UNIX_COMPAT
#include <sprite.h>
#include <stdio.h>
#include <stdlib.h>
#include <status.h>
#include <errno.h>
#include <user/sys/types.h>
#include <user/sys/wait.h>
#include <user/sys/time.h>
#include <user/sys/resource.h>
#include <user/sys/signal.h>
#include <mach.h>
#include <proc.h>
#include <procUnixStubs.h>
#include <vm.h>
#include <fsutil.h>
#include <assert.h>
#include <sig.h>
#include <sigInt.h>
#include <compatInt.h>
extern unsigned int sigBitMasks[SIG_NUM_SIGNALS];
extern int sigDefActions[SIG_NUM_SIGNALS];
extern int sigCanHoldMask;
int debugSigStubs;
/*
*----------------------------------------------------------------------
*
* Sig_KillStub --
*
* Procedure to map from Unix kill system call to Sprite.
*
* Results:
* Error code is returned upon error. Otherwise SUCCESS is returned.
*
* Side effects:
* Side effects associated with the system call.
*
*----------------------------------------------------------------------
*/
int
Sig_KillStub(pid, sig)
int pid;
int sig;
{
ReturnStatus status;
int spriteSignal;
if (debugSigStubs) {
printf("Sig_KillStub(0x%x, 0x%x)\n", pid, sig);
}
status = Compat_UnixSignalToSprite(sig, &spriteSignal);
if (status == FAILURE || (spriteSignal == NULL && sig != 0)) {
status = SYS_INVALID_ARG;
} else {
if (pid == 0) {
pid = PROC_MY_PID;
}
status = Sig_UserSend(spriteSignal, pid, FALSE);
}
if (status != SUCCESS) {
Mach_SetErrno(Compat_MapCode(status));
return -1;
}
return 0;
}
/*
*----------------------------------------------------------------------
*
* Sig_KillpgStub --
*
* Procedure to map from Unix killpg system call to Sprite.
*
* Results:
* Error code is returned upon error. Otherwise SUCCESS is returned.
*
* Side effects:
* Side effects associated with the system call.
*
*----------------------------------------------------------------------
*/
int
Sig_KillpgStub(pgrp, sig)
int pgrp;
int sig;
{
ReturnStatus status;
int spriteSignal;
if (debugSigStubs) {
printf("Sig_KillpgStub(0x%x, 0x%x)\n", pgrp, sig);
}
status = Compat_UnixSignalToSprite(sig, &spriteSignal);
if (status == FAILURE || (spriteSignal == NULL && sig != 0)) {
Mach_SetErrno(EINVAL);
return -1;
}
status = Sig_UserSend(spriteSignal, pgrp, TRUE);
if (status != SUCCESS) {
Mach_SetErrno(Compat_MapCode(status));
return -1;
}
return 0;
}
/*
*----------------------------------------------------------------------
*
* Sig_SigvecStub --
*
* Procedure to map from Unix sigvec system call to Sprite Sig_SetAction.
*
* Results:
* Error code is returned upon error. Otherwise SUCCESS is returned.
*
* Side effects:
* The signal handler associated with the specified signal is modified.
*
*----------------------------------------------------------------------
*/
int
Sig_SigvecStub(sig, newVectorPtr, oldVectorPtr)
int sig; /* Signal to set the vector for. */
struct sigvec *newVectorPtr; /* New vector. */
struct sigvec *oldVectorPtr; /* Old vector. */
{
int spriteSignal; /* Equivalent signal for Sprite */
Sig_Action newAction; /* Action to take */
Sig_Action oldAction; /* Former action */
ReturnStatus status; /* Generic result code */
struct sigvec newVector;
struct sigvec oldVector;
Proc_ControlBlock *procPtr = Proc_GetActualProc();
Address dummy;
if (debugSigStubs) {
printf("Sig_SigvecStub(%d, %x, %x)\n", sig, newVectorPtr,
oldVectorPtr);
}
/*
* Set magic flag to indicate we're in Unix signal mode.
*/
procPtr->unixProgress = PROC_PROGRESS_UNIX;
status = Compat_UnixSignalToSprite(sig, &spriteSignal);
if (status == FAILURE || spriteSignal == NULL) {
Mach_SetErrno(EINVAL);
return -1;
}
if (newVectorPtr != (struct sigvec *)NULL) {
status = Vm_CopyIn(sizeof(struct sigvec), (Address)newVectorPtr,
(Address)&newVector);
if (status != SUCCESS) {
Mach_SetErrno(Compat_MapCode(status));
return -1;
}
switch ((int)newVector.sv_handler) {
case SIG_DFL:
newAction.action = SIG_DEFAULT_ACTION;
break;
case SIG_IGN:
newAction.action = SIG_IGNORE_ACTION;
break;
default:
newAction.action = SIG_HANDLE_ACTION;
newAction.handler = (int (*)())newVector.sv_handler;
}
status = Compat_UnixSigMaskToSprite(newVector.sv_mask,
&newAction.sigHoldMask);
if (status == FAILURE) {
printf("Sig_SigvecStub: compat failure\n");
Mach_SetErrno(EINVAL);
return -1;
}
/*
* Make sure that the signal is in range.
*/
if (spriteSignal < SIG_MIN_SIGNAL || spriteSignal >= SIG_NUM_SIGNALS ||
spriteSignal == SIG_KILL || spriteSignal == SIG_SUSPEND) {
/*
printf("Sig_SigvecStub: bad signal %d\n", spriteSignal);
*/
Mach_SetErrno(EINVAL);
return -1;
}
/*
* There are two cases:
*
* 1) The current action really contains a handler to call. Thus
* the current action is SIG_HANDLE_ACTION.
* 2) The current action is one of the other four actions.
*/
if (procPtr->sigActions[spriteSignal] > SIG_NUM_ACTIONS) {
oldAction.action = SIG_HANDLE_ACTION;
oldAction.handler = (int (*)())procPtr->sigActions[spriteSignal];
oldAction.sigHoldMask = procPtr->sigMasks[spriteSignal];
} else {
if (procPtr->sigActions[spriteSignal]
== sigDefActions[spriteSignal]) {
oldAction.action = SIG_DEFAULT_ACTION;
} else {
oldAction.action = procPtr->sigActions[spriteSignal];
}
}
/*
* Make sure that the action is valid.
*/
if (newAction.action < 0 || newAction.action > SIG_NUM_ACTIONS) {
printf("Sig_SigvecStub: invalid action %d\n", newAction.action);
Mach_SetErrno(EINVAL);
return -1;
}
if (newAction.action == SIG_DEFAULT_ACTION) {
newAction.action = sigDefActions[spriteSignal];
}
/*
* Store the action. If it is SIG_HANDLE_ACTION then the handler
* is stored in place of the action.
*/
if (newAction.action == SIG_HANDLE_ACTION) {
if (Vm_CopyIn(4, (Address) ((unsigned int) (newAction.handler)),
(Address) &dummy) != SUCCESS) {
Mach_SetErrno(EFAULT);
return -1;
}
procPtr->sigMasks[spriteSignal] = (sigBitMasks[spriteSignal]
| newAction.sigHoldMask) & sigCanHoldMask;
procPtr->sigActions[spriteSignal] = (unsigned int) newAction.handler;
} else if (newAction.action == SIG_IGNORE_ACTION) {
/*
* Only actions that can be blocked can be ignored. This prevents a
* user from ignoring a signal such as a bus error which would cause
* the process to take a bus error repeatedly.
*/
if (sigBitMasks[spriteSignal] & sigCanHoldMask) {
procPtr->sigActions[spriteSignal] = SIG_IGNORE_ACTION;
Proc_Lock(procPtr);
SigClearPendingMask(procPtr, spriteSignal);
if (spriteSignal == SIG_SUSPEND) {
procPtr->genFlags &= ~(PROC_PENDING_SUSPEND |
PROC_RESUME_PROCESS);
}
Proc_Unlock(procPtr);
} else {
Mach_SetErrno(EINVAL);
return -1;
}
procPtr->sigMasks[spriteSignal] = 0;
} else {
procPtr->sigActions[spriteSignal] = newAction.action;
procPtr->sigMasks[spriteSignal] = 0;
}
}
if (oldVectorPtr != NULL) {
switch (oldAction.action) {
case SIG_DEFAULT_ACTION:
oldVector.sv_handler = SIG_DFL;
break;
case SIG_IGNORE_ACTION:
oldVector.sv_handler = SIG_IGN;
break;
default:
oldVector.sv_handler = (void (*)())oldAction.handler;
break;
}
(void) Compat_SpriteSigMaskToUnix(oldAction.sigHoldMask,
&oldVector.sv_mask);
oldVector.sv_flags = 0;
status = Vm_CopyOut(sizeof(oldVector), (Address)&oldVector,
(Address)oldVectorPtr);
if (status != SUCCESS) {
Mach_SetErrno(EFAULT);
return -1;
}
}
return 0;
}
/*
*----------------------------------------------------------------------
*
* Sig_SigblockStub --
*
* Procedure to map from Unix sigblock system call to Sprite.
*
* Results:
* Error code is returned upon error. Otherwise SUCCESS is returned.
*
* Side effects:
* Side effects associated with the system call.
*
*----------------------------------------------------------------------
*/
int
Sig_SigblockStub(mask)
int mask; /* additional bits to mask */
{
int spriteMask = 0; /* equivalent mask for Sprite */
int oldSpriteMask; /* old mask, in Sprite terms */
ReturnStatus status; /* generic result code */
register Proc_ControlBlock *procPtr = Proc_GetActualProc();
int oldMask;
if (debugSigStubs) {
printf("Sig_SigblockStub(%x)\n", mask);
}
status = Compat_UnixSigMaskToSprite(mask, &spriteMask);
if (status == FAILURE) {
Mach_SetErrno(EINVAL);
return -1;
}
oldSpriteMask = procPtr->sigHoldMask;
if (status == FAILURE) {
Mach_SetErrno(EINVAL);
return -1;
}
procPtr->sigHoldMask = (spriteMask | oldSpriteMask) & sigCanHoldMask;
procPtr->specialHandling = 1;
status = Compat_SpriteSigMaskToUnix(oldSpriteMask, &oldMask);
if (status == FAILURE) {
Mach_SetErrno(EINVAL);
return -1;
}
return oldMask;
}
/*
*----------------------------------------------------------------------
*
* Sig_SigsetmaskStub --
*
* Procedure to map from Unix sigsetmask system call to Sprite.
*
* Results:
* Error code is returned upon error. Otherwise SUCCESS is returned.
*
* Side effects:
* Side effects associated with the system call.
*
*----------------------------------------------------------------------
*/
int
Sig_SigsetmaskStub(mask)
int mask; /* new mask */
{
int spriteMask = 0; /* equivalent mask for Sprite */
int oldSpriteMask; /* old mask, in Sprite terms */
ReturnStatus status; /* generic result code */
int oldMask;
register Proc_ControlBlock *procPtr;
if (debugSigStubs) {
printf("Sig_SigsetmaskStub(%x)\n");
}
procPtr = Proc_GetActualProc();
status = Compat_UnixSigMaskToSprite(mask,&spriteMask);
if (status == FAILURE) {
Mach_SetErrno(EINVAL);
return -1;
}
procPtr->sigHoldMask = spriteMask & sigCanHoldMask;
oldSpriteMask = procPtr->sigHoldMask;
procPtr->sigHoldMask = spriteMask & sigCanHoldMask;
procPtr->specialHandling = 1;
status = Compat_SpriteSigMaskToUnix(oldSpriteMask, &oldMask);
if (status == FAILURE) {
Mach_SetErrno(EINVAL);
return -1;
}
return oldMask;
}
/*
*----------------------------------------------------------------------
*
* Sig_SigpauseStub --
*
* Procedure to map from Unix sigpause system call to Sprite.
*
* Results:
* Error code is returned upon error. Otherwise SUCCESS is returned.
*
* Side effects:
* Side effects associated with the system call.
*
*----------------------------------------------------------------------
*/
int
Sig_SigpauseStub(mask)
int mask; /* new mask */
{
int spriteMask = 0; /* equivalent mask for Sprite */
ReturnStatus status; /* generic result code */
if (debugSigStubs) {
printf("Sig_Sigpause\n");
}
status = Compat_UnixSigMaskToSprite(mask,&spriteMask);
if (status == FAILURE) {
Mach_SetErrno(EINVAL);
return -1;
}
status = Sig_Pause(spriteMask);
if (debugSigStubs) {
printf("Sig_Sigpause done\n");
}
Mach_SetErrno(EINTR);
if (status == GEN_ABORTED_BY_SIGNAL) {
Proc_GetCurrentProc()->unixProgress = PROC_PROGRESS_RESTART;
} else {
Proc_GetCurrentProc()->unixProgress = PROC_PROGRESS_MIG_RESTART;
}
return -1;
}
/*
*----------------------------------------------------------------------
*
* sigstack --
*
* Procedure to fake the Unix sigstack system call.
*
* Results:
* Error code is returned upon error. Otherwise SUCCESS is returned.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
/*ARGSUSED*/
int
Sig_SigstackStub(ss, oss)
struct sigstack *ss, *oss;
{
struct sigstack oldStack;
if (debugSigStubs) {
printf("Sig_SigstackStub\n");
}
if (oss != NULL) {
oldStack.ss_sp = 0;
oldStack.ss_onstack = 0;
Vm_CopyOut(sizeof(struct sigstack), (Address)&oldStack,
(Address)oss);
}
return 0;
}